#include "widget.h"
#include "ui_widget.h"
#include "sockethandler.h"
#include <QMessageBox>
#include "creategroup.h"
#include "downloadfile.h"
#include "createmeeting.h"
#include "onlinemeeting.h"
#include <QFileDialog>
#include <QTime>


Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    ui->frame_linkServer->show();
    ui->frame_login->hide();
    ui->frame_main->hide();
    this->setFixedSize(this->geometry().size()); // 禁止窗口尺寸改变
//    this->setWindowFlag(Qt::FramelessWindowHint); // 去掉标题栏

    connect(socketHandler::getInstance(), &socketHandler::regState, this, &Widget::onRegState);
    connect(socketHandler::getInstance(), &socketHandler::logState, this, &Widget::onLoginState);
    connect(socketHandler::getInstance(), &socketHandler::onlineUsers, this, &Widget::onOnlineUsers);
    connect(socketHandler::getInstance(), &socketHandler::privateChat, this, &Widget::onPrivateChat);
    connect(socketHandler::getInstance(), &socketHandler::groupChat, this, &Widget::onGroupChat);
    connect(socketHandler::getInstance(), &socketHandler::createGroupState, this, &Widget::onCreateGroupState);
    connect(socketHandler::getInstance(), &socketHandler::addGroup, this, &Widget::onAddGroup);
    connect(socketHandler::getInstance(), &socketHandler::upload, this, &Widget::onUpload);
    connect(socketHandler::getInstance(), &socketHandler::downloadFile, this, &Widget::onDownLoadFile);
    connect(socketHandler::getInstance(), &socketHandler::groupFile, this, &Widget::onGroupFile);
    connect(socketHandler::getInstance(), &socketHandler::retMeeting, this, &Widget::onRetMeeting);
    connect(socketHandler::getInstance(), &socketHandler::inviteMeeting, this, &Widget::onInviteMeeting);
    connect(socketHandler::getInstance(), &socketHandler::clearMeeting, this, &Widget::onClearMeeting);


    connect(socketHandler::getInstance()->getSocket(), &QTcpSocket::disconnected, this, [this](){flag = true; this->close();});
}

Widget::~Widget()
{
    socketHandler::removeInstance();
    delete ui;
}

void Widget::closeEvent(QCloseEvent *event)
{
    emit quitWidget();
    do {
//        if (flag)
        {

            closeThis();
            event->accept();
            break ;
        }
//        QMessageBox::StandardButton reply;
//        reply = QMessageBox::question(this, "确认关闭", "你确定要关闭窗口吗?", QMessageBox::Yes|QMessageBox::No);
//        if (reply == QMessageBox::Yes) {
//            emit quitWidget();
//            closeThis();
//            event->accept();
//        } else {
//            event->ignore();
//            return ;
//        }
    }while(false);

}

void Widget::closeThis()
{
    for (auto pair : chatObj)
    {
        delete pair.first;
    }
    chatObj.clear();
    for (auto pair : groupObj)
    {
        delete pair.first;
    }
    groupObj.clear();
}

void Widget::on_btn_link_clicked()
{
    if (socketHandler::getInstance()->connectServe("127.0.0.1",8888))
    {
        ui->frame_linkServer->hide();
        ui->frame_login->show();
        return ;
    }
    QMessageBox::warning(this, "连接", "服务器未启动!");
}

// 注册按钮点击槽函数
void Widget::on_btn_register_clicked()
{
    QString name = ui->le_name->text();
    QString pswd = ui->le_pswd->text();
    if (name.isEmpty() || pswd.isEmpty())
    {
        QMessageBox::warning(this, "注册", "用户名或密码不能为空");
        return ;
    }
    messagePackage message;
    message.setType(messagePackage::Register);
    message.setUserName(name);
    message.setUserPassword(pswd);
    message.sendMessage(&message, socketHandler::getInstance()->getSocket());
}

// 登录按钮点击槽函数
void Widget::on_btn_login_clicked()
{
    QString name = ui->le_name->text();
    QString pswd = ui->le_pswd->text();
    if (name.isEmpty() || pswd.isEmpty())
    {
        QMessageBox::warning(this, "登录", "用户名或密码不能为空");
        return ;
    }

    messagePackage message;
    message.setType(messagePackage::Login);
    message.setUserName(name);
    message.setUserPassword(pswd);
    message.sendMessage(&message, socketHandler::getInstance()->getSocket());
}

// 注册槽函数
void Widget::onRegState(bool ret)
{
    if (ret) QMessageBox::information(this, "注册", "注册成功");
    else QMessageBox::warning(this, "注册", "注册失败,用户名已存在");
}

// 登录状态槽函数
void Widget::onLoginState(int value)
{
    if (value == 1)
    {
//        QMessageBox::information(this, "登录", "登录成功");
        this->setWindowTitle(ui->le_name->text());
        this->userName = ui->le_name->text();
        ui->frame_login->hide();
        ui->frame_main->show();
    }
    else if (value == -1) QMessageBox::warning(this, "登录", "登录失败,该用户名已在其它设备登录");
    else QMessageBox::warning(this, "登录", "登录失败,用户名或密码错误");
}

// 在线用户更新
void Widget::onOnlineUsers(QStringList users)
{
    int size = ui->lw_onlineUsers->count();
    ui->lw_onlineUsers->clear();
    for (auto user : users)
    {
        if (user == this->userName) continue;
        QListWidgetItem *item = new QListWidgetItem(user);
        item->setTextAlignment(Qt::AlignCenter);
        ui->lw_onlineUsers->addItem(item);
    }
    if (size > ui->lw_onlineUsers->count())
    {
        for (auto user : chatObj.keys())
        {
            QList<QListWidgetItem *> item = ui->lw_onlineUsers->findItems(user, Qt::MatchExactly);
            if (!item.isEmpty()) continue;
            auto it = chatObj.find(user);
            it.value().first->hide();
            it.value().first->deleteLater();
            chatObj.erase(it);
            QMessageBox::information(this, "通知",QString("%1已下线").arg(user));
            break;
        }
    }
}

// 在线用户列表双击槽函数
void Widget::on_lw_onlineUsers_itemDoubleClicked(QListWidgetItem *item)
{
    QString name = item->text();
    if (chatObj.find(name) == chatObj.end())
    {
        PrivateChat * obj = new PrivateChat(this->userName, name);
        obj->show();
        chatObj[name] = QPair<PrivateChat*,bool>(obj, true);

        connect(this, &Widget::quitWidget, obj, &QWidget::close);
        connect(this, &Widget::newInfo, obj, &PrivateChat::onNewInfo);
        connect(obj, &PrivateChat::sendInfo, this, &Widget::onPrivateChatSendInfo);
        connect(obj, &PrivateChat::chatClose, this, &Widget::onChatClose);

        return;
    }
    else {
        auto obj = chatObj[name];
        if (obj.second == true){
            obj.first->hide();
            chatObj[name] = QPair<PrivateChat*,bool>(obj.first, false);
        }
        else
        {
            obj.first->show();
            chatObj[name] = QPair<PrivateChat*,bool>(obj.first, true);
        }
    }
}

// 私聊发送消息
void Widget::onPrivateChatSendInfo(QString sender, QString receiver, QString info, QString time)
{
    messagePackage pack;
    pack.setType(messagePackage::PrivateChat);
    pack.setSender(sender);
    pack.setReceiver(receiver);
    pack.setInfo(info);
    pack.setTime(time);
    pack.sendMessage(&pack, socketHandler::getInstance()->getSocket());
}

// 私聊接受信息
void Widget::onPrivateChat(messagePackage pack)
{
    QString sender = pack.sender();
    QString receiver = pack.receiver();
    if (receiver != this->userName)
    {
        qDebug() << "error";
        return ;
    }
    if (chatObj.find(sender) == chatObj.end())
    {
        PrivateChat * obj = new PrivateChat(this->userName, sender);
        obj->show();
        chatObj[sender] = QPair<PrivateChat*,bool>(obj, true);

        connect(this, &Widget::quitWidget, obj, &QWidget::close);
        connect(obj, &PrivateChat::sendInfo, this, &Widget::onPrivateChatSendInfo);
        connect(this, &Widget::newInfo, obj, &PrivateChat::onNewInfo);
        connect(obj, &PrivateChat::chatClose, this, &Widget::onChatClose);
    }
    emit newInfo(pack);
}

// 私聊对话框关闭槽函数
void Widget::onChatClose(QString receiver)
{
    auto it = chatObj.find(receiver);
    it.value().second = false;
}

// 创建群聊按钮点击槽
void Widget::on_btn_createGroup_clicked()
{
    CreateGroup *cg = new CreateGroup(this->userName);
    connect(this, &Widget::quitWidget, cg, &QWidget::close);
    connect(socketHandler::getInstance(), &socketHandler::allUsers, cg, &CreateGroup::onAllUsers);
    connect(cg, &CreateGroup::group, this, &Widget::onGroup);

    messagePackage pack;
    pack.setType(messagePackage::AllUsers);
    pack.setUserName(this->userName);
    messagePackage::sendMessage(&pack, socketHandler::getInstance()->getSocket());
    cg->show();
}

// 创建群聊
void Widget::onGroup(QStringList users, QString groupName)
{
    this->show();
    messagePackage pack;
    pack.setType(messagePackage::Group);
    pack.setUserName(userName);
    pack.setGroupName(groupName);
    pack.setAllUsers(users);
    messagePackage::sendMessage(&pack, socketHandler::getInstance()->getSocket());
}

// 创建群聊槽函数
void Widget::onCreateGroupState(messagePackage pack)
{
    if (!pack.ret())
    {
        QMessageBox::warning(this, "创建组", "该组已存在");
        return ;
    }
    QListWidgetItem *item = new QListWidgetItem(pack.groupName());
    item->setTextAlignment(Qt::AlignCenter);
    ui->lw_group->addItem(item);
}

// 群聊双击槽函数
void Widget::on_lw_group_itemDoubleClicked(QListWidgetItem *item)
{
    QString groupName = item->text();
    if (groupObj.find(groupName) == groupObj.end())
    {
        GroupChat * obj = new GroupChat(this->userName, groupName);
        obj->show();
        groupObj[groupName] = QPair<GroupChat*,bool>(obj, true);

        connect(this, &Widget::quitWidget, obj, &QWidget::close);
        connect(this, &Widget::newGroupInfo, obj, &GroupChat::onNewGroupInfo);
        connect(obj, &GroupChat::sendInfo, this, &Widget::onGroupChatSendInfo);
        connect(obj, &GroupChat::chatClose, this, &Widget::onGroupChatClose);
        connect(obj, &GroupChat::inviteGroup, this, &Widget::onInviteGroup);

        return;
    }
    else {
        auto obj = groupObj[groupName];
        if (obj.second == true){
            obj.first->hide();
            groupObj[groupName] = QPair<GroupChat*,bool>(obj.first, false);
        }
        else
        {
            obj.first->show();
            groupObj[groupName] = QPair<GroupChat*,bool>(obj.first, true);
        }
    }
}

// 群聊发送消息
void Widget::onGroupChatSendInfo(QString sender, QString groupName, QString info, QString time)
{
    messagePackage pack;
    pack.setType(messagePackage::GroupChat);
    pack.setSender(sender);
    pack.setGroupName(groupName);
    pack.setInfo(info);
    pack.setTime(time);
    pack.sendMessage(&pack, socketHandler::getInstance()->getSocket());
}

// 群聊对话框关闭槽函数
void Widget::onGroupChatClose(QString groupName)
{
    auto it = groupObj.find(groupName);
    it.value().second = false;
}

// 群聊接收信息
void Widget::onGroupChat(messagePackage pack)
{

    QString sender = pack.sender();
    QString groupName = pack.groupName();
    if (sender == this->userName)
    {
        return ;
    }
    if (groupObj.find(groupName) == groupObj.end())
    {
        GroupChat * obj = new GroupChat(this->userName, groupName);
        obj->show();
        groupObj[groupName] = QPair<GroupChat*,bool>(obj, true);

        connect(this, &Widget::quitWidget, obj, &QWidget::close);
        connect(this, &Widget::newGroupInfo, obj, &GroupChat::onNewGroupInfo);
        connect(obj, &GroupChat::sendInfo, this, &Widget::onGroupChatSendInfo);
        connect(obj, &GroupChat::chatClose, this, &Widget::onGroupChatClose);
        connect(obj, &GroupChat::inviteGroup, this, &Widget::onInviteGroup);
    }
    emit newGroupInfo(pack);
}

// 邀请入群槽函数
void Widget::onInviteGroup(QString name, QString groupName)
{
    messagePackage pack;
    pack.setType(messagePackage::InviteGroup);
    pack.setSender(userName);
    pack.setReceiver(name);
    pack.setGroupName(groupName);
    messagePackage::sendMessage(&pack, socketHandler::getInstance()->getSocket());
}

// 添加群至群聊列表
void Widget::onAddGroup(QString groupName)
{
    QListWidgetItem *item = new QListWidgetItem(groupName);
    item->setTextAlignment(Qt::AlignCenter);
    ui->lw_group->addItem(item);
}

// 上传文件按钮点击槽函数
void Widget::on_btn_upload_clicked()
{
    QString filePath = QFileDialog::getOpenFileName(this, "上传文件", "../MeetingClient/file/", "ALL (*.*)");
    if (filePath.isEmpty()) return ;
    QString fileName = QFileInfo(filePath).fileName();
    QFile file(filePath);
    if (!file.open(QIODevice::ReadOnly))
    {
        qDebug() << "无法打开文件:" << filePath;
        return ;
    }
    QByteArray fileData = file.readAll();

    messagePackage pack;
    pack.setType(messagePackage::UploadFile);
    pack.setFileName(fileName);
    pack.setFileData(fileData);
    pack.setSender(userName);

    messagePackage::sendMessage(&pack, socketHandler::getInstance()->getSocket());

    file.close();
}

// 上传文件结果槽函数
void Widget::onUpload(bool ret)
{
    if (ret) QMessageBox::information(this, "上传文件", "上传成功");
    else QMessageBox::warning(this, "上传文件", "上传失败,已存在同名文件");
}

// 下载文件点击槽函数
void Widget::on_btn_download_clicked()
{
    messagePackage pack;
    pack.setType(messagePackage::AllFile);
    messagePackage::sendMessage(&pack, socketHandler::getInstance()->getSocket());

    DownloadFile *obj = new DownloadFile(userName);

    connect(this, &Widget::quitWidget, obj, &QWidget::close);
    connect(socketHandler::getInstance(), &socketHandler::allFile, obj, &DownloadFile::onAllFile);
    connect(obj, &DownloadFile::objClose, this, &Widget::show);
    connect(obj, &DownloadFile::download, this, &Widget::onDownload);

    this->hide();
    obj->show();
}

// 下载请求
void Widget::onDownload(QString file)
{
    this->show();
    messagePackage pack;
    pack.setType(messagePackage::DownloadFile);
    pack.setFileName(file);
    pack.setSender(userName);
    messagePackage::sendMessage(&pack, socketHandler::getInstance()->getSocket());
}

// 获取下载文件
void Widget::onDownLoadFile(messagePackage pack)
{
    QString filePath = QFileDialog::getSaveFileName(nullptr, "保存文件", "../MeetingClient/downfile/"+pack.fileName(), "All Files (*);;Text Files (*.txt)");
    if (filePath.isEmpty())return ;
    QFile file(filePath);

    file.open(QIODevice::WriteOnly);

    file.write(pack.fileData());

    file.close();
}

// 群分享文件
void Widget::onGroupFile(messagePackage pack)
{
    QString sender = pack.sender();
    if (sender == userName) return ;
    QMessageBox::StandardButton reply;
    reply = QMessageBox::question(this, "群文件分享", sender + "分享了群文件, 是否接收?", QMessageBox::Yes|QMessageBox::No);
    if (reply == QMessageBox::Yes) {
        QString filePath = QFileDialog::getSaveFileName(nullptr, "保存文件", "../MeetingClient/downfile/"+pack.fileName(), "All Files (*);;Text Files (*.txt)");
        if (filePath.isEmpty())return ;
        QFile file(filePath);
        file.open(QIODevice::WriteOnly);
        file.write(pack.fileData());
        file.close();
    } else {
        return ;
    }
}

// 创建会议按钮点击槽函数
void Widget::on_btn_createMeeting_clicked()
{
    if (isMeeting)
    {
        QMessageBox::warning(this, "创建会议", "正在会议中");
        return ;
    }
    CreateMeeting *cg = new CreateMeeting(this->userName);
    cg->show();
    connect(this, &Widget::quitWidget, cg, &QWidget::close);
    connect(socketHandler::getInstance(), &socketHandler::allUsers, cg, &CreateMeeting::onAllUsers);
    connect(cg, &CreateMeeting::meeting, this, &Widget::onMeeting);

    messagePackage pack;
    pack.setType(messagePackage::AllUsers);
    pack.setUserName(this->userName);
    messagePackage::sendMessage(&pack, socketHandler::getInstance()->getSocket());
}

// 创建会议请求
void Widget::onMeeting(QStringList users, QString meetingName)
{
    messagePackage pack;
    QString time = QTime::currentTime().toString();
    pack.setType(messagePackage::Meeting);
    pack.setSender(userName);
    pack.setMeetingName(meetingName);
    pack.setAllUsers(users);
    pack.setTime(time);
    messagePackage::sendMessage(&pack, socketHandler::getInstance()->getSocket());
}

// 创建会议请求结果返回槽函数
void Widget::onRetMeeting(messagePackage pack)
{
    if (pack.ret() == false)
    {
        QMessageBox::information(this, "创建会议", "服务器繁忙,无法创建");
        return ;
    }
    isMeeting = true;
    OnlineMeeting *obj = new OnlineMeeting(pack.meetingName(), userName, pack.ip(), pack.port(), true);
    obj->show();
    connect(this, &Widget::quitWidget, obj, &QWidget::close);
    connect(socketHandler::getInstance(), &socketHandler::updateMeeting, obj, &OnlineMeeting::onUpdateMeeting);
    connect(obj, &OnlineMeeting::closeMeeting, this, &Widget::onCloseMeeting);
    // ...
}

// 邀请入会槽函数
void Widget::onInviteMeeting(messagePackage pack)
{
    if (isMeeting) return ;

    QMessageBox::StandardButton reply;
    reply = QMessageBox::question(this, "邀请入会", pack.sender() + "邀请你加入会议,是否加入?", QMessageBox::Yes|QMessageBox::No);
    if (reply == QMessageBox::Yes) {
        OnlineMeeting *obj = new OnlineMeeting(pack.meetingName(), userName, pack.ip(), pack.port());
        obj->show();
        connect(this, &Widget::quitWidget, obj, &QWidget::close);
        connect(socketHandler::getInstance(), &socketHandler::updateMeeting, obj, &OnlineMeeting::onUpdateMeeting);
        connect(obj, &OnlineMeeting::closeMeeting, this, &Widget::onCloseMeeting);
        connect(socketHandler::getInstance(), &socketHandler::clearMeeting, obj, &QWidget::close);
        isMeeting = true;

        messagePackage update;
        update.setType(messagePackage::UpdateMeeting);
        update.setSender(userName);
        update.setPort(pack.port());
        messagePackage::sendMessage(&update, socketHandler::getInstance()->getSocket());
    } else {
        return ;
    }
}

void Widget::onCloseMeeting()
{
    isMeeting = false;
}

void Widget::onClearMeeting()
{
    QMessageBox::information(this, "会议", "会议结束");
}
